package top.wardyan.wtask.tapd.api;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.jfinal.kit.Prop;

import cn.hutool.core.lang.Console;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import top.wardyan.base.common.annotation.Service;
import top.wardyan.base.common.config.ConfigProp;
import top.wardyan.base.common.db.kits.ProcKit;
import top.wardyan.base.common.util.DateUtil;
import top.wardyan.wtask.tapd.vo.Story;
import top.wardyan.wtask.tapd.vo.StoryData;
import top.wardyan.wtask.tapd.vo.TapdStoryResponse;
import top.wardyan.wtask.tapd.vo.TapdTaskResponse;
import top.wardyan.wtask.tapd.vo.Task;
import top.wardyan.wtask.tapd.vo.TaskData;


/**
 * 
 * @author harrydeep@wardyan.top
 * 2024-12-07
 */
@Service
public class TapdBusiness {

	private static final cn.hutool.log.Log log = cn.hutool.log.Log.get();
	private static final Prop PROP = ConfigProp.load();
	private static final String DSC_TOKEN = PROP.get("dsc_token");
	private static final String COOKIE = PROP.get("Cookie");
	private static final String workspace_ids = PROP.get("workspace_ids");; 
	
	private static final Integer PAGESIZE = 100;
	private static final String TAPD_API_URL = "https://www.tapd.cn/api/search_filter/search_filter/search";
	private static final Map<String,Object> STORYQUERYPARAM_DATETIME = new HashMap<String,Object>(){{
		this.put("entity", "story");
		this.put("id", "15");
		this.put("fieldIsSystem", "1");
		this.put("fieldDisplayName", "标题");
		this.put("fieldOption", "between");
		this.put("fieldSystemName","created");
		this.put("fieldType", "datetime");
		this.put("value", "");
		this.put("fieldLabel", "创建时间");
		this.put("selectOption", new JSONArray());
	}};
	

	private static final Map<String,Object> STORYQUERYPARAM_UPDATE = new HashMap<String,Object>(){{
		this.put("fieldOption", "between");
		this.put("fieldType", "datetime");
		this.put("entity", "story");
		this.put("fieldSystemName", "modified");
		this.put("fieldDisplayName", "状态");
		this.put("selectOption", new JSONArray());
		this.put("value", "");
		this.put("fieldIsSystem", "1");
		this.put("id", "16");
		this.put("fieldLabel", "最后修改时间");
	}};
	
	private static final Map<String,Object> TASKQUERYPARAM_DATETIME = new HashMap<String,Object>(){{
		this.put("entity", "task");
		this.put("id", "15");
		this.put("fieldIsSystem", "1");
		this.put("fieldDisplayName", "标题");
		this.put("fieldOption", "between");
		this.put("fieldSystemName","created");
		this.put("fieldType", "datetime");
		this.put("value", "");
		this.put("fieldLabel", "创建时间");
		this.put("selectOption", new JSONArray());
	}};
	

	private static final Map<String,Object> TASKQUERYPARAM_UPDATE = new HashMap<String,Object>(){{
		this.put("fieldOption", "between");
		this.put("fieldType", "datetime");
		this.put("entity", "task");
		this.put("fieldSystemName", "modified");
		this.put("fieldDisplayName", "状态");
		this.put("selectOption", new JSONArray());
		this.put("value", "");
		this.put("fieldIsSystem", "1");
		this.put("id", "16");
		this.put("fieldLabel", "最后修改时间");
	}};

	private static final Map<String,Object> STORYQUERYPARAM = new HashMap<String,Object>(){{
		this.put("data", new ArrayList<Object>() {{
			this.add(STORYQUERYPARAM_DATETIME);
			this.add(STORYQUERYPARAM_UPDATE);
		}});
		this.put("optionType", "OR");
		this.put("needInit", "1");
	}};
	

	

	private static final Map<String,Object> TASKQUERYPARAM = new HashMap<String,Object>(){{
		this.put("data", new ArrayList<Object>() {{
			this.add(TASKQUERYPARAM_DATETIME);
			this.add(TASKQUERYPARAM_UPDATE);
		}});
		this.put("optionType", "OR");
		this.put("needInit", "1");
	}};
	

	private void yp_tapd_story(Story story) {
		ProcKit.exec("yp_tapd_story", new HashMap<String,Object>(){{
			this.put("pCustID",story.getIteration_id());
			this.put("pCust",story.getIteration_name());
			this.put("pStoryID",story.getId());
			this.put("pName",story.getName());
			this.put("pStatus",story.getStatus());
			this.put("pLabel",story.getLabel());
			this.put("pPriority",story.getPriority());
			this.put("pOwner",story.getOwner());
			this.put("pWorkspace",story.getWorkspace_name());
			this.put("pCreator",story.getCreator());
			this.put("pCreateDate",story.getCreated());
			this.put("pEndDate",story.getDue());
			this.put("pWorkspaceID",story.getWorkspace_id());
		}});
	}
	private void yp_tapd_task(Task task) {
		ProcKit.exec("yp_tapd_task", new HashMap<String,Object>(){{
			this.put("pCustID",task.getIterationId());
			this.put("pStoryID",task.getStoryId());
			this.put("pTaskID",task.getId());
			this.put("pName",task.getName());
			this.put("pStatus",task.getStatus());
			this.put("pLabel",task.getLabel());
			this.put("pPriority",task.getPriority());
			if(task.getCustom_field_搞开发的人() != null && task.getCustom_field_搞开发的人().length() > 0) {
				this.put("pOwner",task.getCustom_field_搞开发的人());
			}else {
				this.put("pOwner",task.getOwner());
			}
			Float hour = 0.0F;
			if(task.getEffortCompleted() > 0) {
				hour = task.getEffortCompleted();
			}else {
				hour = task.getCustom_field_开发工时();
			}
			this.put("pHour",hour);
			this.put("pBegin",task.getBegin());
			this.put("pWorkspace",task.getWorkspaceName());
			this.put("pCreateDate",task.getCreated());
			this.put("pPlanHour",0.0);
			this.put("pLastUpdate",task.getModified());
			this.put("pFinishTime",task.getCompleted());
			this.put("pEnd",task.getDue());
			this.put("pWorkspaceID",task.getWorkspaceId());
		}});
	}

	public void yp_tapd_dealdeleted() {
		ProcKit.exec("yp_tapd_dealdeleted", new HashMap<String,Object>(){{}});
	}
	
	
	public void spy(Timestamp begin, Timestamp end) {
		
	}


    private static final Map<String, String> header = new HashMap<>() {{
	    this.put("Host", "www.tapd.cn");
	    this.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0");
	    this.put("Accept", "application/json, text/plain, */*");
	    this.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
	    this.put("Accept-Encoding", "gzip, deflate, br, zstd");
	    this.put("Content-Type", "application/json");
	    this.put("Origin", "https://www.tapd.cn");
	    this.put("DNT", "1");
	    this.put("Connection", "keep-alive");
	    this.put("Referer", "https://www.tapd.cn/tapd_fe/worktable/search?queryToken=da8a1eccd18fc1286b7c4ced79962839&view_change_obj=1");
	    this.put("Cookie", COOKIE);
	    this.put("Sec-Fetch-Dest", "empty");
	    this.put("Sec-Fetch-Mode", "cors");
	    this.put("Sec-Fetch-Site", "same-origin");
	    this.put("Priority", "u=0");
    }};

    private static final Map<String, Object> STORY_DATA = new HashMap<>() {{
	    String paramstring = JSONObject.toJSONString(STORYQUERYPARAM);
	    this.put("workspace_ids", workspace_ids);
	    this.put("search_data", paramstring);
	    this.put("obj_type", "story");
	    this.put("search_type", "base");
	    this.put("page", 1);
	    this.put("perpage", PAGESIZE);
	    this.put("parallel_token", "");
	    this.put("order_field", "created");
	    this.put("order_value", "desc");
	    this.put("show_fields", new String[]{"id", "name", "status", "iteration_id", "priority", "owner", "creator", "created", "module", "label", "workitem_type_id", "begin", "due", "modified", "completed", "workspace_id"});
	    this.put("display_mode", "list");
	    this.put("version", "1.1.0");
	    this.put("only_gen_token", 0);
	    this.put("exclude_workspace_configs", new JSONArray());
	    this.put("hide_not_match_condition_node", 0);
	    this.put("hide_not_match_condition_sub_node", 0);
	    this.put("dsc_token", DSC_TOKEN);
    
    }};

    

    private static Map<String, Object> TASK_DATA = new HashMap<>() {{
	    String paramstring = JSONObject.toJSONString(TASKQUERYPARAM);
	    this.put("workspace_ids", workspace_ids);
	    this.put("search_data", paramstring);
	    this.put("obj_type", "task");
	    this.put("search_type", "advanced");
	    this.put("page", 1);
	    this.put("perpage", PAGESIZE);
	    this.put("parallel_token", "");
	    this.put("order_field", "created");
	    this.put("order_value", "desc");
	    this.put("show_fields", new String[]{"id","label","name","status","iteration_id","priority","owner","effort_completed","begin","effort","created","modified","completed","custom_field_开发工时","custom_field_开发","story_id","due","creator","custom_field_搞开发的人"});
	    this.put("display_mode", "list");
	    this.put("version", "1.1.0");
	    this.put("only_gen_token", 0);
	    this.put("exclude_workspace_configs", new JSONArray());
	    this.put("hide_not_match_condition_node", 0);
	    this.put("hide_not_match_condition_sub_node", 0);
	    this.put("dsc_token", DSC_TOKEN);
    
    }};


    public void fetchStory(Timestamp beginTime, Timestamp endTime) {
    	long before = System.currentTimeMillis();
    	if(beginTime == null) {
    		beginTime = DateUtil.range(1);
    	}
    	if(endTime == null) {
    		endTime = DateUtil.range(2);
    	}
        String a1 = DateUtil.format(beginTime, DateUtil.SHORT) + "," + DateUtil.format(endTime, DateUtil.SHORT) ;
        STORYQUERYPARAM_DATETIME.put("value", a1);
        STORYQUERYPARAM_UPDATE.put("value", a1);
        
        STORYQUERYPARAM.put("data",  new ArrayList<Object>() {{
			this.add(STORYQUERYPARAM_DATETIME);
			this.add(STORYQUERYPARAM_UPDATE);
		}});

        String paramstring = JSONObject.toJSONString(STORYQUERYPARAM);
        STORY_DATA.put("search_data", paramstring);
        
        int page = 1;
        int maxPage = 1;

        while (page <= maxPage) {
        	STORY_DATA.put("page", page);
            

            String jsonstr = JSON.toJSONString(STORY_DATA);
            HttpRequest req = HttpRequest.post(TAPD_API_URL)
            .headerMap(header, false)
            .body(jsonstr)
            ;
            
            
            HttpResponse response = req.execute();
            String body = response.body();
            TapdStoryResponse tapdresponse = JSONObject.parseObject(body, TapdStoryResponse.class);
            
            
            
            if(tapdresponse != null) {
            	StoryData tapddata = tapdresponse.getData();
            	maxPage = tapddata.getTotal_count() / PAGESIZE + 1;
            	Console.log(DateUtil.formatNowFull() , " 需求 页码: " , page , " 总页数: " , maxPage);
            	List<Story> storys = tapddata.getList();
            	for(Story story : storys) {
            		// this.yp_tapd_story(null, body, null, body, begintime, endtime, a1, paramstring, jsonstr, body, null, null)
            		this.yp_tapd_story(story);
            	}
            }
            Integer second = RandomUtil.randomInt(5, 15);
            page += 1;
            while(second > 0 && page <= maxPage) {
            	Console.log("暂停一会,假装是个人在操作...等待时间秒:{},当前页:{},总页数:{}", second, page, maxPage);
            	ThreadUtil.sleep(1000);
            	second -= 1;
            }
        }

        if(maxPage  < 1) {
        	log.info("TAPD需求一页都没有,结束爬取");
        }else {
        	log.info("TAPD需求爬取完成,总页数:{},总耗时ms:{}", maxPage, System.currentTimeMillis() - before);
        }
    }

    
    
    
    
    

    public void fetchTask(Timestamp beginTime, Timestamp endTime) {
    	long before = System.currentTimeMillis();
    	if(beginTime == null) {
    		beginTime = DateUtil.range(1);
    	}
    	if(endTime == null) {
    		endTime = DateUtil.range(2);
    	}
        String a1 = DateUtil.format(beginTime, DateUtil.SHORT) + "," + DateUtil.format(endTime, DateUtil.SHORT) ;
        TASKQUERYPARAM_DATETIME.put("value", a1);
        TASKQUERYPARAM_UPDATE.put("value", a1);
        
        TASKQUERYPARAM.put("data",  new ArrayList<Object>() {{
			this.add(TASKQUERYPARAM_DATETIME);
			this.add(TASKQUERYPARAM_UPDATE);
		}});

        String paramstring = JSONObject.toJSONString(TASKQUERYPARAM);
        TASK_DATA.put("search_data", paramstring);
        
        int page = 1;
        int maxPage = 1;

        while (page <= maxPage) {
        	TASK_DATA.put("page", page);
            
            HttpRequest.closeCookie();
            String jsonstr = JSONObject.toJSONString(TASK_DATA);
            HttpRequest req = HttpRequest.post(TAPD_API_URL)
            .headerMap(header, true)
            .body(jsonstr)
            ;
            
            
            HttpResponse response = req.execute();
            
            String body = response.body();
            TapdTaskResponse tapdresponse = JSON.parseObject(body, TapdTaskResponse.class);
            
            
            
            if(tapdresponse != null && tapdresponse.getData() != null) {
            	TaskData tapddata = tapdresponse.getData();
            	maxPage = tapddata.getTotal_count() / PAGESIZE + 1;
            	Console.log(DateUtil.formatNowFull() , " 任务 页码: " , page , " 总页数: " , maxPage , ", 总行数:" , tapddata.getTotal_count());
            	List<Task> tasks = tapddata.getList();
            	for(Task task : tasks) {
            		// this.yp_tapd_story(null, body, null, body, begintime, endtime, a1, paramstring, jsonstr, body, null, null)
            		this.yp_tapd_task(task);
            	}
            }
            Integer second = RandomUtil.randomInt(15, 20);
            page += 1;
            while(second > 0 && page <= maxPage) {
            	Console.log("暂停一会,假装是个人在操作...等待时间秒:{},当前页:{},总页数:{}", second, page, maxPage);
            	ThreadUtil.sleep(1000);
            	second -= 1;
            }
        }
        if(maxPage  < 1) {
        	log.info("TAPD任务一页都没有,结束爬取");
        }else {
        	log.info("TAPD任务爬取完成,总页数:{},总耗时ms:{}", maxPage, System.currentTimeMillis() - before);
        }
    }

}
